/*********************************************************************/
char    *name="smsnd6";
char    *usage="2001:250:ccce:: [-p 10002] [-ttl 10] [-sec 10] [-s 2001:da8:aaae::6] [-u] [-sleep 3]";

/*
 * Copyright (C) 2008 CERNET Network Center
 * smclock/smjoin/smclock6/smjoin6/smsend6/smrec6
 *
 * Design and coding:
 * Xing Li <xing@cernet.edu.cn>
 * Congxiao Bao <congxiao@cernet.edu.cn>
 *
 * Some portions of the code are copied and modified from
 * mcastClient.c fpont 12/99 pont.net
 * ssmping package * Copyright (C) 2005  Stig Venaas
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 */
/***************************************/
/*
 * Copyright (C) 2005  Stig Venaas <venaas@uninett.no>
 * $Id: ssmping.c,v 1.22 2005/11/29 16:27:26 sv Exp $
 *
 * Contributions:
 * Solaris support by Alexander Gall <gall@switch.ch>
 * Initial Windows support by Nick Lamb <njl@ecs.soton.ac.uk>
 *
 * Permission to use, copy, modify, and distribute this software for any
 * purpose with or without fee is hereby granted, provided that the above
 * copyright notice and this permission notice appear in all copies.
 */
/***************************************/
/* modified from */
/* fpont 12/99   */
/* pont.net      */
/* mcastClient.c */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h> /* close */
#include <sys/time.h> /* select() */

#define SERVER_PORT 1501
#define MAXLINE 100
#define MAX_MSG 100

int timeday2();
void errx(char *, ...);
void err(char *, ...);
char *addr2string(struct sockaddr *, socklen_t);

/*********************************************************************/
int     main (argc,argv)
int     argc;
char    **argv;
{
        int     ki=0, kfi=0, kfin[10];
        char    group[MAXLINE], port[MAXLINE];
        int     sport, raw=0, sec=10, uu=0;
        unsigned long   count = 0;
	int fsport=0;

/*********************************************************************/

  time_t t;
  struct tm *tm;
  char    str[100];

  int sd, rc, i;
  unsigned char ttl = 15;
  struct sockaddr_in6 cliAddr, servAddr;
  struct hostent *h;

  char  msg[MAX_MSG];
  int mflag = 1;
  int sss = 0;
  char asource[100];

 	char    line[MAXLINE];
        FILE    *fi;

	int	slp8= 3;

  sport = 1501;

  /* char  out[1000]; */


for (ki = 1; ki < argc; ki++) {

        if ('-' != argv[ki][0])         kfin[++kfi] = ki;

        else if (strcmp("-p", argv[ki]) == 0)   {strcpy(port, argv[++ki]); fsport=1;}
        else if (strcmp("-ttl", argv[ki]) == 0) ttl = atoi(argv[++ki]);
        else if (strcmp("-sec", argv[ki]) == 0) sec = atoi(argv[++ki]);
        else if (strcmp("-sleep", argv[ki]) == 0) slp8 = atoi(argv[++ki]);
        else if (strcmp("-raw", argv[ki]) == 0) raw = 1;
        else if (strcmp("-u", argv[ki]) == 0) uu = 1;
	else if (strcmp("-s", argv[ki]) == 0)    {sss=1; strcpy(asource, argv[++ki]);}

        else {
                fprintf(stderr, "%s: illegal option %s \n", name, argv[ki]);
                fprintf(stderr, "Usage: %s %s \n", name, usage);
                exit(1);
        }
}

        if (argc == 1)  {
                fprintf(stderr, "Usage: %s %s \n", name, usage);
                exit (1);
        }
         strcpy(group, argv[ kfin[1] ]);


  if (fsport == 1)	sport = atoi(port);

  h = gethostbyname2(group, AF_INET6);

  if(h==NULL) {
    printf("%s : unknown host '%s'\n",argv[0],group);
    exit(1);
  }

        memcpy((char *)&servAddr.sin6_addr, h->h_addr, h->h_length);
        servAddr.sin6_family = h->h_addrtype;
        servAddr.sin6_port = htons(sport);

	/* strcpy(out,  addr2string((struct sockaddr *)&servAddr, (socklen_t)sizeof(servAddr)));
         printf("out= %s\n", out); */

  
  /* check if dest address is multicast */
  /* if(!IN_MULTICAST(ntohl(servAddr.sin_addr.s_addr))) {
     printf("%s : given address '%s' is not multicast \n",argv[0],
           inet_ntoa(servAddr.sin_addr)); 
        mflag = 0;
  } */

  /* create socket */
  sd = socket(AF_INET6, SOCK_DGRAM,0);
  if (sd<0) {
    printf("%s : cannot open socket\n",argv[0]);
    exit(1);
  }
 
if (sss == 1) {
  h = gethostbyname2(asource, AF_INET6);
  if(h==NULL) {
    printf("unknown host\n");
    exit(1);
  }
   memcpy((char *)&cliAddr.sin6_addr, h->h_addr, h->h_length);

}
else 	cliAddr.sin6_addr = in6addr_any;

  /* bind any port number */
  cliAddr.sin6_family = AF_INET6;
  
  /* cliAddr.sin_addr.s_addr = htonl(INADDR_ANY); */
  cliAddr.sin6_port = htons(0);

  if(bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr))<0) {
    perror("bind");
    exit(1);
  }

        if (mflag == 1) {
                if(setsockopt(sd,IPPROTO_IP,IP_MULTICAST_TTL, &ttl,sizeof(ttl))<0) {
                printf("%s : cannot set ttl = %d \n",argv[0],ttl);
                exit(1);
                }
                /* printf("%s : sending data on multicast group '%s' (%s)\n",argv[0],
                h->h_name,inet_ntoa(*(struct in_addr *) h->h_addr_list[0])); */
        }
        else {
                /* printf("%s : sending data to host '%s' (%s)\n",argv[0],
                h->h_name,inet_ntoa(*(struct in_addr *) h->h_addr_list[0])); */
        }
  
 	fi=stdin;

  /* send data */
    /* for (i = 0; i<100; i++) { */

   while ( get_line(fi, line, MAXLINE) > 0) {
                /* if (uu == 0) {
                        time(&t);
                        tm = localtime (&t);
                        strftime (str, sizeof (str), "%Y.%m.%d %H:%M:%S %Z", tm);
                }
                else {
                        timeday2(str); 
                } */
		printf("%s", line);
		replace(line, '\n', ' ');
                sprintf(msg, "%s", line);
                /* if (mflag == 1) printf("sending to %s#%d [%s]\n", group, sport, msg); 
                else            printf("sending to host  %s#%d [%s]\n", group, sport, msg); */

                rc = sendto(sd,
                msg,
                strlen(msg)+1,
                0,
                (struct sockaddr *) &servAddr, sizeof(servAddr));
    
    if (rc<0) {
      printf("%s : cannot send data %d\n",argv[0],i-1);
      close(sd);
      exit(1);
    }
        sleep(slp8);
        if (count == (long int)sec)     break;
  }/* end for */

  /* close socket and exit */
  close(sd);
  exit(0);
}


int     timeday2(daytime)
char    daytime[];
{
        struct  timeval tp;
        float sec22, sec, usec;
        time_t t;
        struct tm *tm;
        char str[100], date2[100], sec2[10], zone2[10];

        time(&t);
        tm = localtime (&t);
        strftime (str, sizeof (str), "%Y.%m.%d %H:%M:%S %Z", tm);
        strftime (date2, sizeof (date2), "%Y.%m.%d %H:%M", tm);
        strftime (sec2, sizeof (sec2), "%S", tm);
        strftime (zone2, sizeof (zone2), "%Z", tm);
        sec22 = atof(sec2);

        gettimeofday(&tp, NULL);
        sec = tp.tv_sec;
        usec = tp.tv_usec/1.0e6;

        sec22 = sec22 + usec;
        if (sec22 < 10.0)       sprintf(sec2, "0%f", sec22);
        else                    sprintf(sec2, "%f", sec22);
        sprintf(daytime, "%s:%s %s", date2, sec2, zone2);
        return (0);
}


char *addr2string(struct sockaddr *addr, socklen_t len) {
    static char addr_buf[2][INET6_ADDRSTRLEN];
    static int i = 0;
    i = !i;
    if (getnameinfo(addr, len, addr_buf[i], sizeof(addr_buf[i]),
            NULL, 0, NI_NUMERICHOST)) {
            err("getnameinfo");
        return NULL;
    }
    return addr_buf[i];
}

/*********************************************************************/
get_line (fi, s, lim)
FILE *fi;
char s[];
int lim;
{
   int c, i;
   i=0;
   while ( --lim>0 && (c=getc(fi)) != EOF && c!='\n' )
      s[i++] = c;
   if (c== '\n')
      s[i++] = c;
   s[i]='\0';
   return(i);
}

/*********************************************************************/
replace(s, c, d)
char s[];
int c, d;
{
   int i, j;
   for (i = j = 0; s[i] != '\0'; i++)
      if (s[i] != c)    s[j++] = s[i];
      else              s[j++] = d;
   s[j] = '\0';
}

/*********************************************************************/

